// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

#include "gtest/gtest.h"

#include "Utility/FileSystem/SGFileSystem.h"

#include "DBManager/DBServiceFactory.h"
#include "DBManager/IService/Input/Subcase/ISubcaseService.h"

#include "Import/BDFImport/BDFImport.h"
using namespace SG::DBManager;
using namespace SG::Import;
using namespace SG::Utility;
using SG::DataStructure::Common::Id;
extern std::shared_ptr<DBServiceFactory> DB_SERVICEFACTORY;

class SUBCASEParser : public ::testing::Test
{
  public:
    static void SetUpTestSuite ()
    {
        DB_SERVICEFACTORY->ClearDatabase ();
    }
};

TEST_F (SUBCASEParser, ParseEntry1)
{
    DB_SERVICEFACTORY->ClearDatabase ();

    auto fileTest = SG::Utility::FileSystem::getTestDataPath ("Import/Subcase/multi_subcase.bdf");
    auto _imp     = std::make_shared<BDFImporter> (DB_SERVICEFACTORY);
    _imp->Load (fileTest.c_str ());

    // SG::DataStructure::FEM::Subcase data;
    auto ser     = DB_SERVICEFACTORY->get<ISubcaseService> ();
    auto subcase = ser->GetSubcase ();

    std::vector<SG::DataStructure::Common::Id> ids = ser->GetAllSubcaseID ();
    ASSERT_TRUE (ids.size () == 2);
    ASSERT_TRUE (ids[0] == 10);
    ASSERT_TRUE (ids[1] == 25);

    std::vector<SG::DataStructure::Common::Id> ID1 = { 10 };
    std::vector<SG::DataStructure::Common::Id> ID2 = { 25 };

    auto LAODId1 = ser->GetLoadsetIds (ID1);
    auto LAODId2 = ser->GetLoadsetIds (ID2);
    ASSERT_TRUE (*LAODId1.begin () == 10);
    ASSERT_TRUE (*LAODId2.begin () == 998);
}

#include "DBManager/IService/Result/ElementalStress/IBARStressService.h"
#include "DBManager/IService/Result/IResultDomainsService.h"
using namespace SG::DBManager::Post;
using namespace SG::DataStructure::Post;
TEST_F (SUBCASEParser, ParseEntryAddStress)
{
    DB_SERVICEFACTORY->ClearDatabase ();

    auto fileTest = SG::Utility::FileSystem::getTestDataPath ("Import/Subcase/multi_subcase.bdf");
    auto _imp     = std::make_shared<BDFImporter> (DB_SERVICEFACTORY);
    _imp->Load (fileTest.c_str ());

    auto eleForceDataSet = std::vector<SG::DataStructure::Post::BARStressData>{
        { 1, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16 },
        { 2, 2.1, 3.2, 4.3, 5.4, 6.5, 7.6, 8.7, 9.8, 10.9, 11.1, 12.2, 13.3, 14.4, 15.5, 16 },
        { 3, -1.1, -2.2, -3.3, -4.4, -5.5, -6.6, -7.7, -8.8, -9.9, -10.1, -11.2, -12.3, -13.4, -14.5, -15 },
        { 4, -1.0, -2.0, -3.0, -4.0, -5.0, -6.0, -7.0, -8.0, -9.0, -10.0, -11.0, -12.0, -13.0, -14.0, -15 },
        { 5, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.1, 11.2, 12.3, 13.4, 14.5, 15 }

    };

    auto service = DB_SERVICEFACTORY->get<IBARStressService> ();
    ASSERT_EQ (service->Add (DomainRequest (static_cast<Id> (25), 0), eleForceDataSet), SG::DataStructure::Common::Status::STATUS_Success);

    std::vector<SG::DataStructure::Post::BARStressData> result;
    ASSERT_EQ (service->Find (1, result), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (result.size (), eleForceDataSet.size ());
    for (std::size_t i = 0; i < eleForceDataSet.size (); ++i)
    {
        ASSERT_EQ (result[i].m_eId, eleForceDataSet[i].m_eId);
        ASSERT_EQ (result[i].m_X1A, eleForceDataSet[i].m_X1A);
        ASSERT_EQ (result[i].m_X2A, eleForceDataSet[i].m_X2A);
        ASSERT_EQ (result[i].m_X3A, eleForceDataSet[i].m_X3A);
        ASSERT_EQ (result[i].m_X4A, eleForceDataSet[i].m_X4A);
        ASSERT_EQ (result[i].m_AX, eleForceDataSet[i].m_AX);
        ASSERT_EQ (result[i].m_MAXA, eleForceDataSet[i].m_MAXA);
        ASSERT_EQ (result[i].m_MINA, eleForceDataSet[i].m_MINA);
        ASSERT_EQ (result[i].m_MST, eleForceDataSet[i].m_MST);
        ASSERT_EQ (result[i].m_X1B, eleForceDataSet[i].m_X1B);
        ASSERT_EQ (result[i].m_X2B, eleForceDataSet[i].m_X2B);
        ASSERT_EQ (result[i].m_X3B, eleForceDataSet[i].m_X3B);
        ASSERT_EQ (result[i].m_X4B, eleForceDataSet[i].m_X4B);
        ASSERT_EQ (result[i].m_MAXB, eleForceDataSet[i].m_MAXB);
        ASSERT_EQ (result[i].m_MINB, eleForceDataSet[i].m_MINB);
        ASSERT_EQ (result[i].m_MSC, eleForceDataSet[i].m_MSC);
    }

    auto domainService = DB_SERVICEFACTORY->get<IResultDomainsService> ();

    ResultDomains resultDomain;
    ASSERT_EQ (domainService->FindById (1, _OUT resultDomain), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (resultDomain.m_id, 1);
    ASSERT_EQ (resultDomain.m_Subcase, 25);
    ASSERT_EQ (resultDomain.m_Step, 0);
    ASSERT_EQ (resultDomain.m_Analysis, SG::DataStructure::Post::AnalysisType::ANALYSISTYPE_Buckl);
    ASSERT_EQ (resultDomain.m_TimeFrequencyEigr, 0.0);
    ASSERT_EQ (resultDomain.m_Eigi, 0.0);
}

#include "DBManager/IService/Result/Nodal/IEIGENVECTORService.h"

TEST_F (SUBCASEParser, ParseEntryAddEigenVector)
{
    DB_SERVICEFACTORY->ClearDatabase ();

    auto fileTest = SG::Utility::FileSystem::getTestDataPath ("SGFem/ModalAnalysis/Hexa8_TwoElement_Model.bdf");
    auto _imp     = std::make_shared<BDFImporter> (DB_SERVICEFACTORY);
    _imp->Load (fileTest.c_str ());
    /**
    struct EIGENVECTORData : public NodalBase
    {
        SG::DataStructure::Common::Real m_X        = 0.0;  ///< X component
        SG::DataStructure::Common::Real m_Y        = 0.0;  ///< Y component
        SG::DataStructure::Common::Real m_Z        = 0.0;  ///< Z component
        SG::DataStructure::Common::Real m_RX       = 0.0;  ///< RX component
        SG::DataStructure::Common::Real m_RY       = 0.0;  ///< RY component
        SG::DataStructure::Common::Real m_RZ       = 0.0;  ///< RZ component
        SG::DataStructure::Common::Id   m_domainId = 0;    ///< Domain identifier
    };
     */
    auto                                     insertdata = std::vector<SG::DataStructure::Post::EIGENVECTORData> ();
    SG::DataStructure::Post::EIGENVECTORData data;
    for (SG::DataStructure::Common::Id i = 0; i < 10; ++i)
    {
        data.m_id = i;
        data.m_X  = i * 1.0;
        data.m_Y  = i * 2.0;
        data.m_Z  = i * 3.0;
        data.m_RX = i * 4.0;
        data.m_RY = i * 5.0;
        data.m_RZ = i * 6.0;
        insertdata.push_back (data);
    }

    auto service = DB_SERVICEFACTORY->get<IEIGENVECTORService> ();
    ASSERT_EQ (service->Add (DomainRequest (1L), insertdata), SG::DataStructure::Common::Status::STATUS_Failure);
    ASSERT_EQ (service->Add (DomainRequest (1L, 1), insertdata), SG::DataStructure::Common::Status::STATUS_Success);

    std::vector<SG::DataStructure::Post::EIGENVECTORData> result;
    ASSERT_EQ (service->Find (1, result), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (result.size (), insertdata.size ());
    ASSERT_EQ (service->Find (DomainRequest (1L, 1), result), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (result.size (), insertdata.size ());
    for (std::size_t i = 0; i < insertdata.size (); ++i)
    {
        ASSERT_EQ (result[i].m_id, insertdata[i].m_id);
        ASSERT_EQ (result[i].m_X, insertdata[i].m_X);
        ASSERT_EQ (result[i].m_Y, insertdata[i].m_Y);
        ASSERT_EQ (result[i].m_Z, insertdata[i].m_Z);
        ASSERT_EQ (result[i].m_RX, insertdata[i].m_RX);
        ASSERT_EQ (result[i].m_RY, insertdata[i].m_RY);
        ASSERT_EQ (result[i].m_RZ, insertdata[i].m_RZ);
    }

    auto domainService = DB_SERVICEFACTORY->get<IResultDomainsService> ();

    ResultDomains resultDomain;
    ASSERT_EQ (domainService->FindById (1, _OUT resultDomain), SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (resultDomain.m_id, 1);
    ASSERT_EQ (resultDomain.m_Subcase, 1);
    ASSERT_EQ (resultDomain.m_Step, 0);
    ASSERT_EQ (resultDomain.m_Analysis, SG::DataStructure::Post::AnalysisType::ANALYSISTYPE_Modes);
    ASSERT_EQ (resultDomain.m_TimeFrequencyEigr, 0.0);
    ASSERT_EQ (resultDomain.m_Eigi, 0.0);
}